import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

// 这里提前准备好 要转化的java 对象
class Request {
    public String username;
    public String password;
    // 这里如果写成 private
    // 就务必要提供对应的 getter 和 setter
    // 否则 jackson 只会处理 public 的 属性
}

class Response{
   public boolean ok;
}

@WebServlet("/json")
public class JsonParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 此处约定的格式如下:
        // POST /json
        // Content-Type: application/json
        //
        // {
        //   username: "zhangsan",
        //   password: "123"
        // }

        // 此处响应的格式(也按照 json 来组织):
        // {
        //   ok:true
        // }

        // 读取请求 body 并按照 json 格式解析成 java 对象
        ObjectMapper objectMapper = new ObjectMapper();
        // 读取
       Request request = objectMapper.readValue(req.getInputStream(),Request.class);
        // 解释这一行代码
        // 核心工作就是 把 上面的json格式字符串 映射成 上面的 java 对象
        // 参数: json字符串(json字符串是在 http 的body 中的,                   (第一步: 读取里面的内容)
        // 就需要通过 HttpServletRequest 中的 getInputStream来获取到)
        // 此处把这个流对象直接传给 readValue, readValue 内部就会读取 InputStream 中的所有数据
        // (http 请求的 body, 上面的 json 字符串)
        // 进一步尝试解析
        // 按照上面的 json 格式, 进行解析, 把json 字符串 解析成 Map 键值对   (第二步 : 进行解析)
        // 把 Map 转换成一个java 对象 (在第二步中 就传入了 Request.class, 告诉 readValue 方法内部, 要把当前的 Map 转成啥样的 Java对象)
        // (这一步就是 第三步)
        // (当中的 .class 就是一个类对象, 在反射中的 => 类对象 , 就如 synchronized 里面的 , 类对象就是 写的 Java代码 要被javac编译成 class 文件)
        // readValue 内部, 就可以通过反射 api  创建 出 Request.class实例!!
        // 并且 根据 Request.class 提供的属性名字, 来查询上述 Map, 把得到的结果, 赋值给对应的 属性.

        System.out.println("username= "+request.username);
        System.out.println("password= "+request.password);

        // 处理响应
        Response response = new Response();
        response.ok=true;
        // 把响应对象转换成json字符串
        String respJson = objectMapper.writeValueAsString(response); // readValue的反向操作
        // 1. 通过传入的参数, 获取到类对象, 通过 反射 拿到都有哪些属性
        // 2. 根据属性的名字 拿到属性的值
        // 3. 把属性名字 和 属性值 按照 json 格式 构造成字符串

        resp.setContentType("application/json; charset=utf8");
        resp.getWriter().write(respJson);
    }
}
